/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"),
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup TeeTrusted
 * @{
 *
 * @brief TEE（Trusted Excution Environment）可信执行环境API。
 *
 * 提供安全能力API，例如可信存储、加解密及可信时间等，用于可信应用程序开发。
 *
 * @since 20
 */

/**
 * @file rpmb_driver_rw_api.h
 *
 * @brief 与RPMB驱动的读写相关的API。
 *
 * 提供读取和写入RPMB驱动的功能。
 *
 * @library NA
 * @kit TEEKit
 * @include <TEEKit/rpmb_driver_rw_api.h>
 * @syscap SystemCapability.Tee.TeeClient
 * @since 20
 */

#ifndef RPMB_DRIVER_RW_API_H
#define RPMB_DRIVER_RW_API_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 定义总块数。
 *
 * @since 20
 */
#define TOTAL_BLK 4

/**
 * @brief 定义块的大小。
 *
 * @since 20
 */
#define BLK_SIZE 256

/**
 * @brief 定义总块的大小。
 *
 * @since 20
 */
#define TOTAL_BLK_SIZE (TOTAL_BLK * BLK_SIZE)

/**
 * @brief 定义安全写保护条目的数量。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_ENTRY_NUM 4

/**
 * @brief 定义保留的安全写保护条目数量。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_ENTRY_RESERVED_NUM 3

/**
 * @brief 定义安全写保护条目的保留大小。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_ENTRY_RESERVED_SIZE 16

/**
 * @brief 定义安全写保护帧的保留数量。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_FRAME_RESERVED_NUM 14

/**
 * @brief 定义安全写保护帧的保留结束数量。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_FRAME_RESERVED_END_NUM 176

/**
 * @brief 定义安全写保护块的大小。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_BLK_SIZE 256

/**
 * @brief 定义安全写保护LUN的最大数量。
 *
 * @since 20
 */
#define SEC_WRITE_PROTECT_LUN_MAX 5

/**
 * @brief WPF设置为1表示逻辑单元应禁止修改在LOGICAL BLOCK ADDRESS字段和NUMBER OF LOGICAL BLOCKS字段
 * 指定范围内的LBA的介质。要求写入介质的命令应以CHECK CONDITION状态终止，
 * 并将感知键设置为DATA PROTECT，附加感知码设置为WRITE PROTECTED。
 *
 * @since 20
 */
typedef enum {
    /** 禁用写保护。 */
    SEC_WRITE_PROTECT_DISABLE = 0,
    /** 启用写保护。 */
    SEC_WRITE_PROTECT_ENABLE = 1,
} write_protect_flag;

/**
 * @brief 写保护类型指定如何修改WPF位。
 *
 * @since 20
 */
typedef enum {
    /** WPF位在断电和硬件复位后是持久的。WPF值只能通过写入安全写保护配置块来更改。 */
    NV_TYPE = 0,
    /** WPF位在断电或硬件复位后自动清除为0b。 */
    P_TYPE = 1,
    /** WPF位在断电或硬件复位后自动设置为1b。 */
    NV_AWP_TYPE = 2,
} write_protect_type;

/**
 * @brief 安全写保护条目。
 * +-----+---+---+---+---+---+---+---+----+
 * |     | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0  |
 * +-----+---+---+---+---+---+---+---+----+
 * | 0   |       保留位      |  WFT  | WPF| -> wp_data
 * +-----+---+---+---+---+---+---+---+----+
 * | 1   |           保留位               |
 * +-----+---+---+---+---+---+---+---+----+
 * | 2   |           保留位               |
 * +-----+---+---+---+---+---+---+---+----+
 * | 3   |           保留位               |
 * +-----+---+---+---+---+---+---+---+----+
 * | 4   |     逻辑块地址          | -> logical_blk_addr
 * +-----+                                +
 * | ... |                                |
 * +-----+                                +
 * | 11  |                                |
 * +-----+                                +
 * | 12  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 * | ... |     逻辑块数量             | -> logical_blk_num
 * +-----+---+---+---+---+---+---+---+----+
 * | 15  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 *
 * @since 20
 */
struct rpmb_protect_cfg_blk_entry {
    /** 该字段指定安全写保护区域的第一个逻辑块地址（LBA）。 */
    uint8_t wp_data;
    /** 保留字段。 */
    uint8_t reserved[SEC_WRITE_PROTECT_ENTRY_RESERVED_NUM];
    /** 该字段指定安全写保护区域的第一个逻辑地址的LBA。 */
    uint64_t logical_blk_addr;
    /** 该字段指定属于安全写保护区域的连续逻辑块数量。 */
    uint32_t logical_blk_num;
} __attribute__((packed));


/**
 * @brief 安全写保护配置块仅由RPMB区域0支持。
 *
 * 此配置块用于配置逻辑单元中的安全写保护区域。\n
 * 每个逻辑单元都有一个对应的安全写保护配置块。\n
 * 每个条目表示一个安全写保护区域。\n
 * 如果某个条目未使用，则相关字段的值应为0。\n
 * +-----+---+---+---+---+---+---+---+----+
 * |     | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0  |
 * +-----+---+---+---+---+---+---+---+----+
 * | 0   |              LUN               |
 * +-----+---+---+---+---+---+---+---+----+
 * | 1   |          数据长度              |
 * +-----+---+---+---+---+---+---+---+----+
 * | 2   |                                |
 * +-----+                                +
 * | ... |           保留位               |
 * +-----+                                +
 * | 15  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 * | 16  |                                |
 * +-----+                                +
 * | ... | 安全写保护条目 0                |
 * +-----+                                +
 * | 31  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 * | 32  |                                |
 * +-----+                                +
 * | ... | 安全写保护条目 1                |
 * +-----+                                +
 * | 47  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 * | 48  |                                |
 * +-----+                                +
 * | ... | 安全写保护条目 2                |
 * +-----+                                +
 * | 63  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 * | 64  |                                |
 * +-----+                                +
 * | ... | 安全写保护条目 3                |
 * +-----+                                +
 * | 79  |                                |
 * +-----+---+---+---+---+---+---+---+----+
 * | 80  |                                |
 * +-----+                                +
 * | ... |           保留位               |
 * +-----+                                +
 * | 255 |                                |
 * +-----+---+---+---+---+---+---+---+----+
 *
 * @since 20
 */
struct rpmb_protect_cfg_block {
    /** 逻辑单元号（LUN）。 */
    uint8_t lun;
    /** 数据长度。 */
    uint8_t data_length;
    /** 保留字段。 */
    uint8_t reserved[SEC_WRITE_PROTECT_FRAME_RESERVED_NUM];
    /** 安全写保护条目数组。 */
    struct rpmb_protect_cfg_blk_entry entries[SEC_WRITE_PROTECT_ENTRY_NUM];
    /** 保留字段。 */
    uint8_t reserved_end[SEC_WRITE_PROTECT_FRAME_RESERVED_END_NUM];
} __attribute__((packed));

/**
 * @brief 通过RPMB驱动写入保护配置块。
 *
 * @param lun 指定适用安全写保护的逻辑单元，且0 <= lun <= SEC_WRITE_PROTECT_LUN_MAX。
 * @param entries 指定安全写保护条目数组，最大长度为4。
 * @param len 指定安全写保护条目数组的实际长度，值小于4。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_BAD_PARAMETERS：输入参数不正确。\n
 *         TEE_ERROR_OUT_OF_MEMORY：发送消息失败。
 * @since 20
 */
TEE_Result tee_ext_rpmb_protect_cfg_blk_write(uint8_t lun, struct rpmb_protect_cfg_blk_entry *entries, uint32_t len);

/**
 * @brief 通过RPMB驱动读取保护配置块。
 *
 * @param lun 指定适用安全读取保护的逻辑单元，且0 <= lun <= SEC_WRITE_PROTECT_LUN_MAX。
 * @param entries 指定安全读取保护条目数组，最大长度为4。
 * @param len 指定安全读取保护条目数组的实际长度，值小于4。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_BAD_PARAMETERS：输入参数不正确。\n
 *         TEE_ERROR_OUT_OF_MEMORY：发送消息失败。
 * @since 20
 */
TEE_Result tee_ext_rpmb_protect_cfg_blk_read(uint8_t lun, struct rpmb_protect_cfg_blk_entry *entries, uint32_t *len);

/**
 * @brief 向RPMB驱动写入明文缓冲区数据。
 *
 * @param buf 指定写入数据的缓冲区。
 * @param size 指定缓冲区的长度，最大值为1024。
 * @param block 指定起始块的位置索引，取值范围为[0,3]。
 * @param offset 指定数据位置的偏移字节，偏移字节值小于256。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_BAD_PARAMETERS：输入参数不正确。\n
 *         TEE_ERROR_OUT_OF_MEMORY：发送消息失败。
 * @since 20
 */
TEE_Result tee_ext_rpmb_driver_write(const uint8_t *buf, size_t size, uint32_t block, uint32_t offset);

/**
 * @brief 从RPMB驱动读取明文缓冲区。
 *
 * @param buf 表示用于读取数据的缓冲区。
 * @param size 表示缓冲区的长度，最大值为1024。
 * @param block 指定起始块的位置索引，取值范围为[0,3]。
 * @param offset 表示数据位置的偏移字节，偏移字节的值小于256。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_BAD_PARAMETERS：输入参数不正确。\n
 *         TEE_ERROR_OUT_OF_MEMORY：发送消息失败。
 * @since 20
 */
TEE_Result tee_ext_rpmb_driver_read(uint8_t *buf, size_t size, uint32_t block, uint32_t offset);

/**
 * @brief 从RPMB驱动移除数据。
 *
 * @param size 表示移除数据的长度，最大值为1024。
 * @param block 指定起始块的位置索引，取值范围为[0,3]。
 * @param offset 表示数据位置的偏移字节，偏移字节的值小于256。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_BAD_PARAMETERS：输入参数不正确。\n
 *         TEE_ERROR_OUT_OF_MEMORY：发送消息失败。
 * @since 20
 */
TEE_Result tee_ext_rpmb_driver_remove(size_t size, uint32_t block, uint32_t offset);

/**
 * @brief RPMB安全存储全格式化操作
 *
 * @return TEE_SUCCESS：函数执行成功
 *         TEE_ERROR_RPMB_GENERIC：RPMB控制器通用错误。\n
 *         TEE_ERROR_RPMB_MAC_FAIL：RPMB控制器MAC校验失败。\n
 *         TEE_ERROR_RPMB_RESP_UNEXPECT_MAC：表示RPMB响应数据MAC校验失败。
 * @since 20
 */
TEE_Result tee_ext_rpmb_format();

#ifdef __cplusplus
}
#endif

#endif
/** @} */